#include <iostream>
#include <fstream>
//#include <mpi.h>
#include <omp.h>
#include <codecvt>
#include <locale>
//#include <sys/time.h>
#include <chrono>

#include "grid_io.hpp"
#include "grid_struct.hpp"
#include "kdtree.hpp"

#define datatype double

using namespace std;

/*
double mysecond()
{
    struct timeval tp;
    struct timezone tpz;
    int i = gettimeofday(&tp, &tpz);
    return ((double)tp.tv_sec * 1000 + (double)tp.tv_usec * 1e-3);
}
*/

double mysecond()
{
    using namespace std::chrono;
    auto now = high_resolution_clock::now();
    auto duration = now.time_since_epoch();
    return duration_cast<milliseconds>(duration).count();
}

int main(int argc, char **argv)
{
    const std::string src_grid_file = "../../../../../data/Grid_and_data.txt";
    // const std::string src_grid_file = "Question2/test_and_data.txt";
    const std::string dst_grid_file = "../../../../../data/Result_grid_coordinates.txt";
    const std::string output_file = "../../../../../data/Our_Answer_uniform0.txt";

    size_t totalLines_src = 0, totalLines_dst = 0;
    std::vector<FEM_struct<datatype>> gridDataArray;
    datatype axisMax[3], axisMin[3];
    int numGridX = 201, numGridY = 101, numGridZ = 51;
    int GirdMax[3] = { numGridX, numGridY, numGridZ }, GridMin[3] = { 0, 0, 0 };
    // int myid, num_procs;

    Serial_read_FEM_sourcegrid<datatype>(src_grid_file, gridDataArray, axisMax, axisMin);

    double Ctime = 0.0;
    Ctime = -mysecond();
    KDTree3D<FEM_struct<datatype>, datatype> tree(gridDataArray);
    Ctime += mysecond();

    std::cout << "Construct Tree Cost " << Ctime << " ms." << std::endl;

    Serial_read_FEM_destgrid<datatype>(dst_grid_file, gridDataArray);

    double Stime = 0.0;
    Stime = -mysecond();
    #pragma omp parallel for
    for (int i = 0; i < gridDataArray.size(); ++i)
    {
        tree.K_Interpolation(gridDataArray[i], 8);
    }

    Stime += mysecond();

    Serial_store_FEM_destgrid<datatype>(output_file, gridDataArray);

    std::cout << "Search Point Cost " << Stime << " ms." << std::endl;

    return 0;
}